package vip.ola.pay.batchpay;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import vip.ola.core.common.constant.PayConstant;
import vip.ola.core.common.util.MyLog;
import vip.ola.core.common.util.PayDigestUtil;
import vip.ola.core.common.util.PayUtil;
import vip.ola.core.common.util.RedisUtil;
import vip.ola.core.entity.AgentpayPassageAccount;
import vip.ola.core.entity.TransOrder;
import vip.ola.pay.channel.BaseTrans;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static vip.ola.core.common.constant.PayEnum.ERR_0121;

/**
 * @author: dingzhiwei
 * @date: 17/12/25
 * @description:
 */
@Service
public class YousTransService extends BaseTrans {

    private static final MyLog _log = MyLog.getLog(YousTransService.class);

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public String getChannelName() {
        return PayConstant.CHANNEL_NAME_ALIPAY;
    }

    public JSONObject trans(TransOrder transOrder) {
        JSONObject retObj = buildRetObj();
        String orderId = transOrder.getTransOrderId();
        BigDecimal amount = new BigDecimal(transOrder.getAmount()).divide(new BigDecimal(100));
        AgentpayPassageAccount payPassageAccount = rpcCommonService.rpcAgentpayPassageAccountService.findById(transOrder.getPassageAccountId());
        if (payPassageAccount == null || StringUtils.isBlank(payPassageAccount.getParam())) {
            return PayUtil.makeRetFail(ERR_0121);
        }
        JSONObject accountParams = JSONObject.parseObject(payPassageAccount.getParam());
        String notifyUrl = accountParams.getString("notify_url");
        String pollRoute = accountParams.getString("pollRoute");
        String failRespCode = accountParams.getString("failRespCode");
        String failNums = accountParams.getString("failNums");
        Long mchId = transOrder.getMchId();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String time = sdf.format(new Date());
        String key= time+":"+mchId;
        Integer tmpPayNums = redisUtil.get(key);
        _log.info("下单请求tmpPayNums={}",tmpPayNums);
        int resultStatus = 1;
        if (tmpPayNums == null){
            redisUtil.set(key, 1, 86400);
            retObj.put("status",1);
        }else {
            int failNumstmp = Integer.valueOf(failNums).intValue();
            if ("0".equals(failNums)){
                if (tmpPayNums % 100 ==0){
                    retObj.put("status",3);
                    Random random = new Random();
                    int num = random.nextInt(5)+1;
                    _log.info("失败tmpPayNums={}，num-》{}",tmpPayNums,num);
                    if(num ==1){
                        retObj.put("channelErrCode", "E001");
                        retObj.put("channelErrMsg", "此卡暂时无法出款，请换卡重新提交");
                    }else if (num ==2){
                        retObj.put("channelErrCode", "E002");
                        retObj.put("channelErrMsg", "暂停非柜面交易，请至柜台办理");
                    }else if (num ==3){
                        retObj.put("channelErrCode", "E003");
                        retObj.put("channelErrMsg", "操作失败:身份证号或手机号或姓名中有1项或多项不符");
                    }else if (num ==4){
                        retObj.put("channelErrCode", "E004");
                        retObj.put("channelErrMsg", "操作失败:该账户已被冻结");
                    }else if (num ==5){
                        retObj.put("channelErrCode", "E005");
                        retObj.put("channelErrMsg", "操作失败:无效卡号");
                    }else if (num ==6){
                        retObj.put("channelErrCode", "E006");
                        retObj.put("channelErrMsg", "操作失败:交易金额超限");
                    }else {
                        retObj.put("channelErrCode", "E001");
                        retObj.put("channelErrMsg", "此卡暂时无法出款，请换卡重新提交");
                    }
                    resultStatus =3;

                }else {
                    retObj.put("status",1);
                }
            }else {
                if (tmpPayNums % failNumstmp ==0){
                    retObj.put("status",3);
                    Random random = new Random();
                    int num = random.nextInt(5)+1;
                    _log.info("失败tmpPayNums={}，num-》{},failNumstmp->{}",tmpPayNums,num,failNumstmp);
                    if(num ==1){
                        retObj.put("channelErrCode", "E001");
                        retObj.put("channelErrMsg", "此卡暂时无法出款，请换卡重新提交");
                    }else if (num ==2){
                        retObj.put("channelErrCode", "E002");
                        retObj.put("channelErrMsg", "暂停非柜面交易，请至柜台办理");
                    }else if (num ==3){
                        retObj.put("channelErrCode", "E003");
                        retObj.put("channelErrMsg", "操作失败:身份证号或手机号或姓名中有1项或多项不符");
                    }else if (num ==4){
                        retObj.put("channelErrCode", "E004");
                        retObj.put("channelErrMsg", "操作失败:该账户已被冻结");
                    }else if (num ==5){
                        retObj.put("channelErrCode", "E005");
                        retObj.put("channelErrMsg", "操作失败:无效卡号");
                    }else if (num ==6){
                        retObj.put("channelErrCode", "E006");
                        retObj.put("channelErrMsg", "操作失败:交易金额超限");
                    }else {
                        retObj.put("channelErrCode", "E001");
                        retObj.put("channelErrMsg", "此卡暂时无法出款，请换卡重新提交");
                    }
                    resultStatus =3;
                }else {
                    retObj.put("status",1);
                }
            }
            tmpPayNums = tmpPayNums +1;
            redisUtil.set(key, tmpPayNums, 86400);
        }
//        try {
//            _log.info("代付转账：" + transOrder.getChannelMchId());
//            AgentpayPassageAccount payPassageAccount = rpcCommonService.rpcAgentpayPassageAccountService.findById(transOrder.getPassageAccountId());
//            if (payPassageAccount == null || StringUtils.isBlank(payPassageAccount.getParam())) {
//                return PayUtil.makeRetFail(ERR_0121);
//            }
//            JSONObject accountParams = JSONObject.parseObject(payPassageAccount.getParam());
//            String mchId = payPassageAccount.getPassageMchId();
//            String orderId = transOrder.getTransOrderId();
//            String payUrl = accountParams.getString("payUrl");
//            String privateKey = accountParams.getString("privateKey");
//            BigDecimal amount = new BigDecimal(transOrder.getAmount()).divide(new BigDecimal(100));
//            TreeMap<String, String> obj = new TreeMap<String, String>();
//            obj.put("name", transOrder.getAccountName().trim());
//            obj.put("ka", transOrder.getAccountNo().trim());
//            obj.put("money", String.valueOf(amount));
//            obj.put("merId", mchId);
//            obj.put("bank", transOrder.getBankName());
//            obj.put("nonceStr", "batch123");
//            obj.put("notifyUrl", accountParams.getString("notify_url"));
//            obj.put("orderId", orderId);
//            // 生成签名
//            StringBuffer paramstr = new StringBuffer();
//            for (String pkey : obj.keySet()) {
//                String pvalue = obj.get(pkey);
//                if (pvalue != null && pvalue != "") {
//                    paramstr.append(pkey + "=" + pvalue + "&");
//                }
//            }
//            String paramsrc = paramstr.substring(0, paramstr.length() - 1);
//            String sign = sign(paramsrc,privateKey);
//            String queryBytes = RSAUtils.sign(sign.getBytes("UTF-8"), PaysUtil.privateKey);
//            obj.put("sign", queryBytes);
//            _log.info("下单请求url={}，param={},json->{}",payUrl,obj,JSONObject.toJSONString(obj));
//            String respData = call(payUrl,obj);
//            _log.info("下单结束respData->{}",respData);
//            JSONObject jsonObject = JSONObject.parseObject(respData);
//            retObj.put("transOrderId", transOrder.getTransOrderId());
//            if (jsonObject != null){
//                String code = jsonObject.getString("code");
//                if ("1".equals(code)){
//                    retObj.put("status",1);
//                }else {
//                    retObj.put("status",3);
//                    retObj.put("channelErrCode", code);
//                    retObj.put("channelErrCode", jsonObject.getString("msg"));
//                }
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            retObj.put("status",3);
//            retObj.put("channelErrCode", e.getMessage());
//        }
//        String respCode ="E001";
//        if ("1".equals(pollRoute)){
//            if (StringUtils.isNotEmpty(failRespCode)){
//                List<String>failRespCodes = Arrays.asList(failRespCode.split("\\,"));
//                if (failRespCodes.contains(respCode)){
//                    //执行轮询
//                    retObj.put("is_poll",1);
//                    retObj.put("status",1);
//                    retObj.put("channelErrCode","E001");
//                    retObj.put("channelErrMsg","卡当日限额");
//                }
//            }
//        }
        if (resultStatus ==1){
            Thread notifyThread = new Thread(()->{
                //自动回调
                try {
                    Random random = new Random();
                    int num = random.nextInt(20)+8;
                    TimeUnit.SECONDS.sleep(num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                NameValuePair pair = new BasicNameValuePair("orderId", orderId);
                NameValuePair pair2 = new BasicNameValuePair("money", String.valueOf(amount));
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(16);
                nameValuePairs.add(pair);
                nameValuePairs.add(pair2);
                String respData = postWithParamsForString(notifyUrl, nameValuePairs);
                _log.info("回调返回={}",respData);
            });
            notifyThread.start();
        }
        return  retObj;
    }

    public static String postWithParamsForString(String url, List<NameValuePair> params){
        HttpClient client = HttpClients.createDefault();
        HttpPost httpPost =   new HttpPost(url);
        String s = "";
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params,"UTF-8"));
            httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
            HttpResponse response = client.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode==200){
                HttpEntity entity = response.getEntity();
                s = EntityUtils.toString(entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }


    public static String call(String url, Map param) {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(url);
        // 响应模型
        CloseableHttpResponse response = null;
        String responseContext = null;
        try {
            StringEntity entity = new StringEntity(JSONObject.toJSONString(param), ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();

            if (responseEntity != null) {
                responseContext = EntityUtils.toString(responseEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContext;
    }



//    public static String call(String url, Map param) {
//        CloseableHttpClient httpClient = getHttpsClient();
//        HttpPost httpPost = new HttpPost(url);
//        // 响应模型
//        CloseableHttpResponse response = null;
//        String responseContext = null;
//        try {
//            StringEntity entity = new StringEntity(JSONObject.toJSONString(param), ContentType.APPLICATION_JSON);
//            httpPost.setEntity(entity);
//            // 由客户端执行(发送)Get请求
//            response = httpClient.execute(httpPost);
//            // 从响应模型中获取响应实体
//            HttpEntity responseEntity = response.getEntity();
//
//            if (responseEntity != null) {
//                responseContext = EntityUtils.toString(responseEntity);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                // 释放资源
//                if (httpClient != null) {
//                    httpClient.close();
//                }
//                if (response != null) {
//                    response.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
////        JSONObject jsonObject = new JSONObject();
////        JSONObject data = new JSONObject();
////        jsonObject.put("code",200);
////        data.put("systemOrderNo",System.currentTimeMillis());
////        jsonObject.put("data",data.toJSONString());
//        return responseContext;
//    }

    /**
     * 获取https连接（不验证证书）
     *
     * @return
     */
    private static CloseableHttpClient getHttpsClient() {
        RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
        ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
        registryBuilder.register("http", plainSF);
        // 指定信任密钥存储对象和连接套接字工厂
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            // 信任任何链接
            TrustStrategy anyTrustStrategy = new TrustStrategy() {

                @Override
                public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException {
                    // TODO Auto-generated method stub
                    return true;
                }
            };
            SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build();
            LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            registryBuilder.register("https", sslSF);
        } catch (KeyStoreException e) {
            throw new RuntimeException(e);
        } catch (KeyManagementException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        Registry<ConnectionSocketFactory> registry = registryBuilder.build();
        // 设置连接管理器
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
        // 构建客户端
        return HttpClientBuilder.create().setConnectionManager(connManager).build();
    }


    private String getSign(Map<String, String> map, String privateKey) {
        String param=map.get("merchantOrderNo")+map.get("appId")+map.get("channelCode")+map.get("payCode")+map.get("payFee")+privateKey;
        String sign = null;
        try {
            sign = PayDigestUtil.md5(param, "UTF-8");
            _log.info("签名:" + sign);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return sign;
    }

    private static String sign(String paramSrc, String privateKey) {
        StringBuffer strbuff = new StringBuffer();
        strbuff.append(paramSrc + "&key=" + privateKey);
        String sign = null;
        try {
            sign = PayDigestUtil.md5(strbuff.toString(), "UTF-8").toUpperCase();
            _log.info("签名:" + sign);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return sign;
    }


    public JSONObject query(TransOrder transOrder) {
        JSONObject retObj = buildRetObj();
        retObj.put("transOrderId", transOrder.getTransOrderId());
////        try {
////            Map<String, String> obj = new HashMap<>();
////            obj.put("merchantOrderNo", transOrder.getTransOrderId());
////            String response=callGet("https://pay.fhpay.pro/order/cashierQuery",obj);
////            _log.info("查询结束respData->{}",response);
////            JSONObject jsonObject = JSONObject.parseObject(response);
////            if (jsonObject != null){
////                String code = jsonObject.getString("code");
////                if ("200".equals(code)){
////                    JSONObject dataObject =JSONObject.parseObject(jsonObject.getString("data"));
////                    if (dataObject!= null && "1".equals(dataObject.getString("orderStatus"))){
////                        retObj.put("status", 2);
////                        retObj.put("channelOrderNo", jsonObject.getString("systemOrderNo"));
////                    }else if (dataObject!= null && "0".equals(dataObject.getString("orderStatus"))){
////                        retObj.put("status", 1);
////                        retObj.put("channelOrderNo", jsonObject.getString("systemOrderNo"));
////                    }else if (dataObject!= null && "2".equals(dataObject.getString("orderStatus"))){
////                        retObj.put("status", 3);
////                        retObj.put("channelOrderNo", jsonObject.getString("systemOrderNo"));
////                    }else if (dataObject!= null && "3".equals(dataObject.getString("orderStatus"))){
////                        retObj.put("status", 2);
////                        retObj.put("channelOrderNo", jsonObject.getString("systemOrderNo"));
////                    }else {
////                        retObj.put("status", 1);
////                        retObj.put("channelOrderNo", jsonObject.getString("systemOrderNo"));
////                    }
////                }else {
////                    retObj.put("status", 1);
////                    retObj.put("channelErrCode", code);
////                    retObj.put("channelErrCode", jsonObject.getString("msg"));
////                }
////            }
////        } catch (Exception e) {
////            e.printStackTrace();
////        }
        retObj.put("status", 2);
        retObj.put("channelOrderNo", "ZY"+System.currentTimeMillis());
        return  retObj;
    }

    public  String callGet(String url, Map<String,String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();

            // 创建http GET请求
            _log.info("请求参数："+uri.toString());
            HttpGet httpGet = new HttpGet(uri);

            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    @Override
    public JSONObject balance(String payParam) {
        return null;
    }



    public static void main (String args[]){
    }


}
